<template>
  <div class="mobile-period-view common-mobile-view">
    <v-calendar ref="calendarRef" :attributes='dailyInfo.attrs'
                @dayclick="dateClick" @did-move="changeMonthClick"
                :is-dark="appStore.isDark"
                class="period-calendar card-item"/>
    <period-legend />

    <period-form />
  </div>
</template>

<script lang="ts" setup>
import PeriodLegend from '@/components/Period/PeriodLegend.vue'
import PeriodForm from '@/components/Period/PeriodForm.vue'
import { CalendarDay } from 'v-calendar/dist/types/src/utils/page'
import { formatDate, getNextDate } from 'vue3-common/utils/dateUtil'
import { onMounted, reactive, watch } from 'vue'
import { usePeriodStore } from '@/store/period.ts'
import { useAppStore } from '@/store/app.ts'
import { IPeriodDay } from '@/types/period.ts'
import dayjs, { Dayjs } from 'dayjs'

const periodStore = usePeriodStore()
const appStore = useAppStore()

const dailyInfo = reactive({
  calendarDate: '',
  menstruateDateList: [],
  sexDateList: [],
  attrs: [] as any[]
})

watch(() => periodStore.isRefresh, async () => {
  dailyInfo.menstruateDateList = []
  dailyInfo.sexDateList = []
  dailyInfo.attrs = []
  updatePeriodDay()

  if (periodStore.periodSetting.isCalculate) {
    const { cycleLength, duration } = periodStore.periodSetting
    // 如果当月存在月经期
    if (dailyInfo.menstruateDateList[0]) {
      calculatePeriodDay(dailyInfo.menstruateDateList[0], cycleLength, duration)
    } else {
      // 否则获取上个月的
      await periodStore.getMenstruateFirstDate(getLastMonth(periodStore.queryInfo.month))
      const predictMenstruateDate = getNextDate(periodStore.menstruateFirstDate, cycleLength, 'days')

      if (predictMenstruateDate) {
        calculatePeriodDay(predictMenstruateDate, cycleLength, duration)
      }
    }
  }
})

onMounted(async () => {
  await periodStore.refreshInfo()
  periodStore.currentPeriodDay = periodStore.getPeriodDay(formatDate(new Date()))
})

const updatePeriodDay = () => {
  periodStore.periodDayList.forEach((item: IPeriodDay) => {
    if (item.isMenstruate) {
      dailyInfo.attrs.push({
        highlight: 'red',
        dates: item.date
      })

      dailyInfo.menstruateDateList.push(item.date)
    }

    if (item.sexActivity !== '') {
      dailyInfo.sexDateList.push(item.date)
      dailyInfo.attrs.push({
        highlight: 'green',
        dates: item.date
      })
    }

    if (item.isDrug) {
      dailyInfo.attrs.push({
        dot: 'red',
        dates: item.date
      })
    }
  })
}

const getAllDatesInMonth = (dateStr: string) => {
  const start = dayjs(dateStr).startOf('month')
  const daysInMonth = start.daysInMonth()
  const dates = []
  for (let i = 0; i < daysInMonth; i++) {
    dates.push(formatDate(start.add(i, 'day')))
  }
  return dates
}

const calculatePeriodDay = (date: string, cycleLength = 28, duration = 5) => {
  const startDate = dayjs(date)
  // 排卵日假设是周期的第 14 天，但对于短周期的情况，排卵日可以在周期的中间附近
  const ovulationDate = startDate.add(cycleLength - 14, 'day') // 基于周期长度来计算排卵日

  const fertileStart = ovulationDate.subtract(5, 'day') // 易孕期为排卵日前5天
  const fertileEnd = ovulationDate.add(4, 'day') // 易孕期为排卵日后4天

  const allDates = getAllDatesInMonth(date)

  for (const dateStr of allDates) {
    const currentDate = dayjs(dateStr)

    // 判断月经期，跳过
    if (currentDate.isSame(startDate, 'day') || checkIsMenstruateDate(currentDate, startDate, duration)) {
      if (!dailyInfo.menstruateDateList.includes(dateStr)) {
        dailyInfo.attrs.push({
          content: 'red',
          dates: formatDate(currentDate)
        })
      }

      continue
    }

    if (dailyInfo.sexDateList.includes(formatDate(currentDate))) {
      continue
    }

    // 判断排卵日
    if (currentDate.isSame(ovulationDate, 'day')) {
      dailyInfo.attrs.push({
        highlight: 'purple',
        dates: dateStr
      })
    } else if (currentDate.isAfter(fertileStart) && currentDate.isBefore(fertileEnd)) {
      // 添加易孕期
      dailyInfo.attrs.push({
        content: 'purple',
        dates: dateStr
      })
    } else {
      // 添加安全期
      dailyInfo.attrs.push({
        content: 'green',
        dates: dateStr
      })
    }
  }
}

const checkIsMenstruateDate = (currentDate: Dayjs, startDate: Dayjs, duration: number) => {
  return currentDate.isAfter(startDate) && currentDate.diff(startDate, 'day') < duration
}

const dateClick = (day: CalendarDay) => {
  periodStore.selectDate = formatDate(day.date)
  periodStore.currentPeriodDay = periodStore.getPeriodDay(formatDate(day.date))
}

/**
 * 选择月份事件
 */
const changeMonthClick = async (value) => {
  periodStore.queryInfo.month = value[0].id
  await periodStore.refreshInfo()
}

const getLastMonth = (current: string): string => {
  const previousMonth = dayjs(current, 'YYYY-MM').subtract(1, 'month')
  return previousMonth.format('YYYY-MM')
}
</script>

<style lang="scss">
.mobile-period-view {
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 1vh;

  .period-calendar {
    justify-self: center;
    align-self: center;
  }
}
</style>
